package org.jrpc.core.registry;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.jrpc.base.ServiceDiscoveryAndRegistry;
import org.jrpc.base.ServiceInfo;
import org.jrpc.base.ServiceInfoManage;
import org.jrpc.common.registry.Constant;
import org.jrpc.core.factory.JrpcConfiguration;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 注册与发现
 */
public class ZooKeeperServiceRegistryAndDiscovery implements ServiceDiscoveryAndRegistry,ApplicationContextAware,InitializingBean {

    private final ZkClient zkClient;

    private ServiceInfo serviceInfo;

    private ServiceInfoManage serviceInfoManage;

    private ApplicationContext applicationContext;

    private JrpcConfiguration jrpcConfiguration;

    public ZooKeeperServiceRegistryAndDiscovery(String address, ServiceInfo serviceInfo) {
        this.zkClient = new ZkClient(address, 5000, 5000);
        this.serviceInfo=serviceInfo;
    }

    public ZooKeeperServiceRegistryAndDiscovery(JrpcConfiguration jrpcConfiguration, ServiceInfoManage serviceInfoManage) {
        this.zkClient = new ZkClient(jrpcConfiguration.getAddress(), 5000, 5000);
        this.serviceInfoManage=serviceInfoManage;
        this.jrpcConfiguration=jrpcConfiguration;
        this.serviceInfo=new ServiceInfo(UUID.randomUUID().toString(),jrpcConfiguration.getServiceName(),
                jrpcConfiguration.getHost(),Integer.parseInt(jrpcConfiguration.getPort()),jrpcConfiguration.getStatus());
    }
    public void listen(){

        zkClient.subscribeDataChanges(Constant.ZK_NOTICE_PATH, new IZkDataListener() {
            //主节点数据修改
            @Override
            public void handleDataChange(String path, Object data) throws Exception {
                ServiceInfo serviceInfo = (ServiceInfo) data;

                System.out.println("修改节点 path=" + path + ", value=" + data);
            }
            //主节点删除
            @Override
            public void handleDataDeleted(String path) throws Exception {
                System.out.println("删除的节点 path" + path);
            }
        });
    }

    @Override
    public String discover(String serviceName) {
        List<String> listServices = zkClient.getChildren(Constant.ZK_REGISTRY_PATH);
        ServiceInfo si=null;
        List<String> serviceNodes=null;
        List<ServiceInfo> serviceInfos = new ArrayList<>();
        String serviceNamePath=null;
        String serviceNode = null;
        for(String service:listServices){
            serviceNamePath=Constant.ZK_REGISTRY_PATH+"/"+service;
            if(zkClient.exists(serviceNamePath)){
                serviceNodes = zkClient.getChildren(serviceNamePath);
                for(String node : serviceNodes){
                    serviceNode=serviceNodes+"/"+node;
                    si = zkClient.readData(serviceNode);
                    if(si!=null){
                        serviceInfos.add(si);
                    }
                }
            }
        }
        serviceInfoManage.setServiceInfoList(serviceInfos);

        return null;
    }

    @Override
    public void register(String serviceName, String serviceAddress) {
        //跟节点
        if(!zkClient.exists(Constant.ZK_REGISTRY_PATH)){
            //创建节点,永久节点
            zkClient.createPersistent(Constant.ZK_REGISTRY_PATH,true);
        }
        //服务
        String servicePath=Constant.ZK_REGISTRY_PATH+"/"+serviceInfo.getServiceName();
        if(!zkClient.exists(servicePath)){
            //创建节点
            zkClient.createPersistent(servicePath,true);
        }
        String notice=Constant.ZK_NOTICE_PATH;
        if(!zkClient.exists(notice)){
            //发送监听节点
            zkClient.createPersistent(notice,serviceInfo);
        }
        //服务节点
        String serviceNodePath=servicePath+"/"+serviceInfo.getId();
        if(!zkClient.exists(serviceNodePath)){
            //创建节点
            zkClient.createEphemeral(serviceNodePath,serviceInfo);

//            System.out.println(zkClient.readData(serviceNodePath).toString());
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //运行注册方法
        register("","");
        discover("");
    }
}
